﻿/// Copyright (c) Microsoft Corporation.  All rights reserved.
using System;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Tcvt.Packages.BuddyBuildServiceProxy;

namespace Tcvt.Packages
{
    public enum LogType
    {
        Informational = 0,
        Error
    }

    public enum BuildValidationType
    {
        Build = 0,
        BuddyBuild
    }

    internal static class Utils
    {
        #region Private Constants
        private const string _userRoot = "HKEY_CURRENT_USER";
        private const string _subkey = "Software\\Microsoft\\TFS Checkin Validation Tool";
        private const string _customXMLLocation = "CustomXMLLocation";
        private const string _enablePriorityOverride = "EnablePriorityOverride";
        private const bool _enablePriorityOverrideDefaultValue = false;
        private const string _verbose = "Verbose"; // values: "" for verbosity off, other for on.
        private const bool _verboseDefaultValue = false;
        private const string _disableTraceInstrumentation = "DisableTraceInstrumentation";
        private const bool _disableTraceInstrumentationDefaultValue = false;
        private const string _enableInformationTraceLogging = "EnableInformationTraceLogging";
        private const bool _enableInformationTraceLoggingDefaultValue = false;
        private const string _defaultLoggingSourceName = "Default";
        private const string _messageBoxTitle = "TFS Check-in Validation Tool";
        #endregion

        #region Public Properties
        public static string KeyName
        {
            get
            {
                return string.Format("{0}\\{1}", _userRoot, _subkey);
            }
            set { }
        }

        public static string BaseKeyName
        {
            get
            {
                return string.Format("{0}\\{1}", _userRoot, _subkey);
            }
            set { }
        }

        public static string Verbose
        {
            get
            {
                return _verbose;
            }
            set { }
        }

        public static bool VerboseDefaultValue
        {
            get
            {
                return _verboseDefaultValue;
            }
            set { }
        }

        public static string DisableTraceInstrumentation
        {
            get
            {
                return _disableTraceInstrumentation;
            }
            set { }
        }

        public static bool DisableTraceInstrumentationDefaultValue
        {
            get
            {
                return _disableTraceInstrumentationDefaultValue;
            }
            set { }
        }

        public static string EnableInformationTraceLogging
        {
            get
            {
                return _enableInformationTraceLogging;
            }
            set { }
        }

        public static bool EnableInformationTraceLoggingDefaultValue
        {
            get
            {
                return _enableInformationTraceLoggingDefaultValue;
            }
            set { }
        }

        public static string EnablePriorityOverride
        {
            get
            {
                return _enablePriorityOverride;
            }
            set { }
        }

        public static bool EnablePriorityOverrideDefaultValue
        {
            get
            {
                return _enablePriorityOverrideDefaultValue;
            }
            set { }
        }

        public static bool IsVerbose
        {
            get
            {
                object registry = Registry.GetValue(Utils.KeyName, Utils.Verbose, Utils.VerboseDefaultValue);
                return (registry == null ? Utils.VerboseDefaultValue : registry.ToString().ToLower() != "false");
            }
            set { }
        }

        public static bool IsTraceInstrumentationDisabled
        {
            get
            {
                object registry = Registry.GetValue(Utils.BaseKeyName, Utils.DisableTraceInstrumentation, Utils.DisableTraceInstrumentationDefaultValue);
                return (registry == null ? Utils.DisableTraceInstrumentationDefaultValue : registry.ToString().ToLower() != "false");
            }
            set { }
        }

        public static bool IsInformationTraceLoggingEnabled
        {
            get
            {
                object registry = Registry.GetValue(Utils.BaseKeyName, Utils.EnableInformationTraceLogging, Utils.EnableInformationTraceLoggingDefaultValue);
                return (registry == null ? Utils.EnableInformationTraceLoggingDefaultValue : registry.ToString().ToLower() != "false");
            }
            set { }
        }

        public static bool IsPriorityOverrideEnabled
        {
            get
            {
                object registry = Registry.GetValue(Utils.BaseKeyName, Utils.EnablePriorityOverride, Utils.EnablePriorityOverrideDefaultValue);
                return (registry == null ? Utils.EnablePriorityOverrideDefaultValue : registry.ToString().ToLower() != "false");
            }
            set { }
        }

        public static string MessageBoxTitle
        {
            get
            {
                return _messageBoxTitle;
            }
            set { }
        }
        #endregion

        #region Public Methods
        public static Version GetProgramVersion()
        {
            return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
        }

        public static void LogMessage(string message)
        {
            Utils.LogMessage(message, LogType.Informational);
        }

        public static void LogMessage(string message, LogType logType)
        {
            if (!IsTraceInstrumentationDisabled)
            {
                if (logType != LogType.Informational ||
                    (logType == LogType.Informational && IsInformationTraceLoggingEnabled))
                {
                    object[] arguments = new object[5];
                    arguments[0] = DateTime.Now.ToLongDateString();
                    arguments[1] = DateTime.Now.ToLongTimeString();
                    arguments[2] = (logType == LogType.Error ? "Error" : "Info");
                    arguments[3] = _defaultLoggingSourceName;
                    arguments[4] = message;
                    string modifiedMessage = string.Format("[{0} {1}]:[{2}]:[{3}]::{4}", arguments);
                    System.Diagnostics.Trace.WriteLine(modifiedMessage);
                }
            }
        }

        public static void ShowInformationMessageBox(string message)
        {
            MessageBox.Show(message, _messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        public static void ShowWarningMessageBox(string message)
        {
            MessageBox.Show(message, _messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        public static void ShowErrorMessageBox(string message)
        {
            MessageBox.Show(message, _messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        public static string GetSerializedRegisteredServers(string[] registeredTfsServers)
        {
            if (registeredTfsServers == null || registeredTfsServers.Length <= 0)
                return string.Empty;

            StringBuilder sb = new StringBuilder();
            sb.Append("\r\n\r\nThe following TFS hosts are registered under your profile:\r\n\r\n");

            for (int i = 0; i < registeredTfsServers.Length; i++)
            {
                sb.AppendFormat("  {0}\r\n", registeredTfsServers[i]);
            }

            sb.Append("\r\nPlease set one of those hosts in the Options page or provide a new one.");
            return sb.ToString();
        }

        public static string[] RegisteredTfsServers()
        {
            try
            {
                return RegisteredServers.GetServerNames();
            }
            catch (Exception ex)
            {
                Utils.LogMessage(string.Format("RegisteredTfsServers: Error getting server names: Message: {0}", ex.Message), LogType.Error);
                Utils.LogMessage(string.Format("RegisteredTfsServers: Error getting server names: {0}", ex.StackTrace), LogType.Error);
                return null;
            }
        }

        public static string GetFormattedDateTime()
        {
            DateTime nowTime = DateTime.Now;
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("{0}-{1}-{2}_{3}-{4}-{5}_{6}",
                nowTime.Month,
                nowTime.Day,
                nowTime.Year,
                nowTime.Hour,
                nowTime.Minute,
                nowTime.Second,
                nowTime.Millisecond);
            return sb.ToString();
        }

        public static int StringArrayContainsValue(string[] stringArray, string valueToFind)
        {
            if (stringArray == null || stringArray.Length == 0)
                return -1;
            if (string.IsNullOrEmpty(valueToFind))
                return -1;
            for (int i = 0; i < stringArray.Length; i++)
            {
                if (string.Compare(stringArray[i], valueToFind, true) == 0)
                    return i;
            }
            return -1;
        }

        public static string CustomXMLLocation
        {
            get
            {
                object registry = Registry.GetValue(Utils.KeyName, _customXMLLocation, string.Empty);
                return registry == null ? string.Empty : registry.ToString();
            }
            set { }
        }

        public static string MsBuildEncodeForLists(string rawMsBuildPropertyValue)
        {
            // Escape ; and =
            return rawMsBuildPropertyValue
                .Replace(";", "%3B")
                .Replace("=", "%3D");
        }

        public static string MsBuildDecodeForLists(string msBuildEncodedPropertyValue)
        {
            // Escape ;
            return msBuildEncodedPropertyValue
                .Replace("%3B", ";")
                .Replace("%3b", ";")
                .Replace("%3D", "=")
                .Replace("%3d", "=");
        }

        public static string EscapeSpecialMsBuildCharacters(string rawMsBuildCommand)
        {
            // List of MSBuild characters to escape:
            // Character Description 
            //  %       Percent sign, used to reference metadata.
            //  $       Dollar sign, used to reference properties.
            //  @       At sign, used to reference item lists.
            //  (       Open parenthesis, used in lists.
            //  )       Close parenthesis, used in lists.
            //  `       Apostrophe (or tick mark), used in conditions and other expressions.
            //  ;       Semicolon, a list separator.
            //  ?       Question mark, a wildcard character when describing a file spec in an item's Include/Exclude section.
            //  *       Asterisk, a wildcard character when describing a file spec in an item's Include/Exclude section.

            // Escape %
            rawMsBuildCommand = rawMsBuildCommand.Replace("%", "%25");
            // Escape $
            rawMsBuildCommand = rawMsBuildCommand.Replace("$", "%24");
            // Escape @
            rawMsBuildCommand = rawMsBuildCommand.Replace("@", "%40");
            // Escape (
            rawMsBuildCommand = rawMsBuildCommand.Replace("(", "%28");
            // Escape )
            rawMsBuildCommand = rawMsBuildCommand.Replace(")", "%29");
            // Escape `
            rawMsBuildCommand = rawMsBuildCommand.Replace("`", "%60");
            // Escape ?
            rawMsBuildCommand = rawMsBuildCommand.Replace("?", "%3F");
            // Escape *
            rawMsBuildCommand = rawMsBuildCommand.Replace("*", "%2A");
            // Escape ;
            rawMsBuildCommand = rawMsBuildCommand.Replace(";", "%3B");

            return rawMsBuildCommand;
        }

        public static string SerializeConfiguredProperties(MsBuildProperty[] configuredParameters)
        {
            if (configuredParameters != null && configuredParameters.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < configuredParameters.Length; i++)
                {
                    sb.AppendFormat("{0}=\"{1}\"",
                        configuredParameters[i].Name,
                        MsBuildEncodeForLists(UnEscapePropertyValue(configuredParameters[i].DefaultValue)));
                    if (i < configuredParameters.Length - 1)
                        sb.Append(";");
                }
                return sb.ToString();
            }
            return string.Empty;
        }

        public static string UnEscapePropertyValue(string propertyValue)
        {
            if (string.IsNullOrEmpty(propertyValue))
                return propertyValue;

            if (!(propertyValue[0] == '\"' && propertyValue[propertyValue.Length - 1] == '\"'))
                return propertyValue;

            return UnEscapePropertyValue(propertyValue.Substring(1, propertyValue.Length - 2));
        }

        #endregion
    }
}
